/*
  Copyright 2009 Tarek Saidi <tarek.saidi@arcor.de>

  This Prayer Times Plasmoid is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 2 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <Plasma/DataContainer>
#include "itl/prayer.h"
#include "plasma-engine-salatinoid.h"


SalatinoidEngine::SalatinoidEngine(QObject* parent, const QVariantList& args) : Plasma::DataEngine(parent)
{
    Q_UNUSED(args);
    //setMinimumUpdateInterval(1000);
    setMinimumPollingInterval(1000);
}

SalatinoidEngine::~SalatinoidEngine()
{
}

bool SalatinoidEngine::sourceRequestEvent(const QString &name)
{
    return updateSourceEvent(name);
}

bool SalatinoidEngine::updateSourceEvent(const QString &name){

    if(!property("latitude").isNull()){
        latitude = property("latitude").toDouble();
        longitude = property("longitude").toDouble();
        seaLevel = property("seaLevel").toInt();
        calculationMethod = property("calculationMethod").toInt();
    }
    else {
        //No properties set... for debugging with PlasmaEngineExplorer
        calculationMethod = 6;
        latitude  = 51.049259; // Dresden :-)
        longitude = 13.73836;
        seaLevel  = 113;

    }

    recalculate();
    setData(name, I18N_NOOP("fajr"),       times[0]);
    setData(name, I18N_NOOP("shurouk"),    times[1]);
    setData(name, I18N_NOOP("zuhr"),       times[2]);
    setData(name, I18N_NOOP("assr"),       times[3]);
    setData(name, I18N_NOOP("maghrib"),    times[4]);
    setData(name, I18N_NOOP("isha"),       times[5]);
    setData(name, I18N_NOOP("nisfullayl"), times[6]);
    setData(name, I18N_NOOP("next_prayer"), nextPrayer);
    setData(name, I18N_NOOP("current_prayer"), currentPrayer);
    return true;
}

void SalatinoidEngine::recalculate()
{
    QDateTime now = QDateTime::currentDateTime();
    Location itl_location;
    Prayer itl_prayers[4][6];
    QDateTime prayers[4][7];
    Method itl_method;
    Date itl_date;

    itl_location.degreeLong  = longitude;
    itl_location.degreeLat   = latitude;
    itl_location.seaLevel    = 0;
    itl_location.pressure    = 1010;
    itl_location.temperature = 10;
    itl_location.gmtDiff     = now.time().hour() - now.toUTC().time().hour();
    itl_location.dst         = 0; //DST is already included in our GMT offset

    getMethod(calculationMethod + 1, &itl_method);

    // Let libITL calculate the prayer times for yesterday, today, tomorrow
    // and the day after tomorrow (needed for midnight calculation)
    for(int d=DAY_YESTERDAY; d<=DAY_AFTER_TOMORROW; d++){
        int dayOffset = d-1;
        itl_date.day   = now.addDays(dayOffset).date().day();
        itl_date.month = now.addDays(dayOffset).date().month();
        itl_date.year  = now.addDays(dayOffset).date().year();
        getPrayerTimes(&itl_location, &itl_method, &itl_date, itl_prayers[d]);
    }

    // Convert from ITL format to Qt format
    for(int d=DAY_YESTERDAY; d<=DAY_AFTER_TOMORROW; d++){
        int dayOffset = d-1;
        for(int i = 0; i < 6; i++) {
            prayers[d][i] = QDateTime(now.date().addDays(dayOffset),
                                      QTime(itl_prayers[d][i].hour,
                                            itl_prayers[d][i].minute,
                                            itl_prayers[d][i].second)
                                      );
            // If Isha is "earlier" than maghrib than this means it is past midnight, so we have to correct the date
            if(prayers[d][PRAYER_ISHA] < prayers[d][PRAYER_MAGHRIB]){
                prayers[d][PRAYER_ISHA] = prayers[d][PRAYER_ISHA].addDays(1);
            }
        }
    }

    // Calculate Islamic midnight for yesterday, today and tomorrow. We need these three times for the following reasons:
    //   Yesterday's: Yesterday's Islamic midnight could be past 0:00, so it's possible that we haven't passed it yet
    //       Today's: If we passed Islamic midnight and we are past 0:00 then we will show the time of the upcoming midnight
    //    Tomorrow's: If Islamic midnight is before 0:00 and we passed it but we did not pass 0:00 yet
    //                then we will already show tomorrow's Islamic midnight

    for(int d=DAY_YESTERDAY; d<=DAY_TOMORROW; d++){
        int halfNightLen = prayers[d][PRAYER_MAGHRIB].secsTo(prayers[d+1][PRAYER_FAJR]) / 2;
        prayers[d][PRAYER_NISFULLAYL] = prayers[d][PRAYER_ISHA].addSecs(halfNightLen);

    }

    //Now we check where we currently are
    for(int d=DAY_YESTERDAY; d<=DAY_AFTER_TOMORROW; d++){
        for(int i = 0; i < 7; i++) {
            if(prayers[d][i] > now){
                nextPrayer = i;
                if(nextPrayer == PRAYER_FAJR || nextPrayer == PRAYER_ZUHR)
                    currentPrayer = -1;
                else
                    currentPrayer = nextPrayer - 1;
                //Finally copy the right times into the output array
                for(int j=0; j<7; j++){
                    times[j] = prayers[d][j];
                }
                return;
            }
        }
    }

    // Program should never reach this point
    for(int j=0; j<7; j++){
        times[j] = QDateTime();
    }
    currentPrayer = -1;
    nextPrayer    =- 1;
    qWarning("prayertimes-dataengine: Error processing prayer time data.");
}

#include "plasma-engine-salatinoid.moc"
